/**
 * @FileName: ProductService.java
 * @Author
 * @Description:
 * @Date 2016年5月27日 上午10:30:21
 * @CopyRight ZTE Corporation
 */
package cn.hpclub.server.service.product;

import java.io.IOException;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.net.MediaType;
import com.jfinal.kit.StrKit;

import cn.hpclub.server.constant.ClientApiConstant;
import cn.hpclub.server.constant.Constant;
import cn.hpclub.server.util.HttpUtil;
import cn.hpclub.server.util.SystemConfigUtil;

public class ProductBusinessService{
    public static final ProductBusinessService service              = new ProductBusinessService();
    private static final int                   REST_RESULT_CODE_SUC = 0;
    private static final Logger                logger               = LoggerFactory
            .getLogger(ProductBusinessService.class);
    private String                             restHostPrefix       = SystemConfigUtil.getSystemConfig()
            .getRestHostPrefix();

    /**
     * @Title: getActivities
     * @Description:TODO
     * @param jsonObject
     * @return JSONObject
     */
    public JSONObject getActivities(JSONObject outData){
        ConcurrentHashMap<String, JSONObject> meansMap = new ConcurrentHashMap<String, JSONObject>();
        ConcurrentHashMap<String, JSONArray> monthMap = new ConcurrentHashMap<String, JSONArray>();
        ConcurrentHashMap<String, JSONArray> feeMap = new ConcurrentHashMap<String, JSONArray>();
        ConcurrentHashMap<String, JSONArray> infoMap = new ConcurrentHashMap<String, JSONArray>();
        JSONObject ljInfo = null;
        JSONObject hyjInfo = null;
        // 1、过滤是合约机活动（MEANS_ID以B开头），还是裸机活动（MEANS_ID以C开头）
        // 2、过滤所有活动（MEANS_ID、MEANS_NAME）
        // 3、过滤每条活动下的所有合约期（RESOURCE_MONTH）
        // 4、过滤每条活动下的每个合约期下的所有保底金额（LOW_FEE）
        // 5、过滤每条活动下的每个合约期下的每笔金额下的所有活动详情
        if(outData != null){
            JSONArray returnInfo = null;
            try{
                returnInfo = outData.getJSONArray(ClientApiConstant.CmccKey.RETURN_INFO);// 有多条数据的时候，RETURN_INFO是个JSON数组
            }
            catch(Exception e){
                logger.error("dpr returnInfo = " + outData.toString());
                returnInfo = new JSONArray();
                JSONObject tmp = outData.getJSONObject(ClientApiConstant.CmccKey.RETURN_INFO);// 只有一条数据的时候，RETURN_INFO是个JSON对象
                returnInfo.put(tmp);
            }
            if(returnInfo != null){
                JSONObject tempObj = null;
                String infoKey = "";
                String monthKey = "";
                String feeKey = "";
                String meansKey = "";

                logger.debug("dpr returnInfo length = " + returnInfo.length());
                for(int i = 0; i < returnInfo.length(); i++){
                    tempObj = returnInfo.getJSONObject(i);

                    // 裸机的第一条数据单独返回：MEANS_ID以C开头的第一条数据，裸机
                    if(ljInfo == null && tempObj.getString("MEANS_ID").indexOf("C") == 0){
                        ljInfo = tempObj;
                    }

                    // 用于统计有没有合约机数据，合约机
                    if(hyjInfo == null && tempObj.getString("MEANS_ID").indexOf("B") == 0){
                        hyjInfo = tempObj;
                    }

                    // 过滤每条活动下的每个合约期下的每笔金额下的所有活动详情
                    infoKey = tempObj.getString("MEANS_ID") + "," + tempObj.getString("RESOURCE_MONTH") + ","
                            + tempObj.getString("LOW_FEE");
                    if(infoMap.get(infoKey) == null){
                        infoMap.put(infoKey, new JSONArray());
                    }
                    infoMap.get(infoKey).put(tempObj);

                    // 过滤每条活动下的每个合约期下的所有保底金额（LOW_FEE）
                    feeKey = tempObj.getString("MEANS_ID") + "," + tempObj.getString("RESOURCE_MONTH");
                    if(feeMap.get(feeKey) == null){
                        feeMap.put(feeKey, new JSONArray());
                    }
                    boolean isFeeExsit = false;
                    for(int j = 0; j < feeMap.get(feeKey).length(); j++){
                        if(StrKit.notBlank(tempObj.getString("LOW_FEE"))
                                && tempObj.getString("LOW_FEE").equals(feeMap.get(feeKey).get(j))){
                            isFeeExsit = true;
                            break;
                        }
                    }
                    if(!isFeeExsit){
                        feeMap.get(feeKey).put(tempObj.getString("LOW_FEE"));
                    }

                    // 过滤每条活动下的所有合约期（RESOURCE_MONTH）
                    monthKey = tempObj.getString("MEANS_ID");
                    if(monthMap.get(monthKey) == null){
                        monthMap.put(monthKey, new JSONArray());
                    }
                    boolean isMonthExsit = false;
                    for(int k = 0; k < monthMap.get(monthKey).length(); k++){
                        if(StrKit.notBlank(tempObj.getString("RESOURCE_MONTH"))
                                && tempObj.getString("RESOURCE_MONTH").equals(monthMap.get(monthKey).get(k))){
                            isMonthExsit = true;
                            break;
                        }
                    }
                    if(!isMonthExsit){
                        monthMap.get(monthKey).put(tempObj.getString("RESOURCE_MONTH"));
                    }

                    // 过滤所有活动（MEANS_ID、MEANS_NAME）
                    meansKey = tempObj.getString("MEANS_ID");
                    if(meansMap.get(meansKey) == null){
                        meansMap.put(meansKey, new JSONObject());
                    }
                    meansMap.get(meansKey).put("MEANS_ID", tempObj.getString("MEANS_ID"));
                    meansMap.get(meansKey).put("MEANS_NAME", tempObj.getString("MEANS_NAME"));
                }
            } else{
                logger.error("dpr returnInfo is null or empty!!!");
            }
        }

        logger.debug("infoMap length = " + infoMap.size());
        return getActObj(meansMap, monthMap, feeMap, infoMap, ljInfo, hyjInfo);
    }

    /**
     * @Title: getActObj
     * @Description:封装活动数据
     * @param meansMap
     * @param monthMap
     * @param feeMap
     * @param infoMap
     * @param ljInfo
     * @param hyjInfo
     * @return JSONObject
     */
    private JSONObject getActObj(ConcurrentHashMap<String, JSONObject> meansMap,
            ConcurrentHashMap<String, JSONArray> monthMap, ConcurrentHashMap<String, JSONArray> feeMap,
            ConcurrentHashMap<String, JSONArray> infoMap, JSONObject ljInfo, JSONObject hyjInfo){
        JSONObject actObj = new JSONObject();
        String hyKey = "B";
        String ljKey = "C";

        actObj.put(hyKey, new JSONObject());
        actObj.getJSONObject(hyKey).put("acts", new JSONArray());
        actObj.getJSONObject(hyKey).put("month", new JSONObject());
        actObj.getJSONObject(hyKey).put("fee", new JSONObject());
        actObj.getJSONObject(hyKey).put("info", new JSONObject());

        actObj.put(ljKey, new JSONObject());
        actObj.getJSONObject(ljKey).put("acts", new JSONArray());
        actObj.getJSONObject(ljKey).put("month", new JSONObject());
        actObj.getJSONObject(ljKey).put("fee", new JSONObject());
        actObj.getJSONObject(ljKey).put("info", new JSONObject());

        actObj.getJSONObject(ljKey).put("firstInfo", ljInfo == null ? new JSONObject() : ljInfo);

        // 如果没有数据，message返回:无数据，请联系BOSS管理员;有数据，message返回空串
        if(hyjInfo == null && ljInfo == null){
            actObj.getJSONObject(hyKey).put("message", ClientApiConstant.Msg.BOSS_NO_DATA);
            actObj.getJSONObject(ljKey).put("message", ClientApiConstant.Msg.BOSS_NO_DATA);

            return actObj;
        } else if(hyjInfo == null && ljInfo != null){
            actObj.getJSONObject(hyKey).put("message", ClientApiConstant.Msg.BOSS_NO_DATA);
            actObj.getJSONObject(ljKey).put("message", "");
        } else if(hyjInfo != null && ljInfo == null){
            actObj.getJSONObject(hyKey).put("message", "");
            actObj.getJSONObject(ljKey).put("message", ClientApiConstant.Msg.BOSS_NO_DATA);
        } else if(hyjInfo != null && ljInfo != null){
            actObj.getJSONObject(hyKey).put("message", "");
            actObj.getJSONObject(ljKey).put("message", "");
        }

        // 活动
        for(Entry<String, JSONObject> item : meansMap.entrySet()){
            if(hyKey.equals(item.getKey().toUpperCase().substring(0, 1))){
                actObj.getJSONObject(hyKey).getJSONArray("acts").put(item.getValue());
            } else{
                actObj.getJSONObject(ljKey).getJSONArray("acts").put(item.getValue());
            }
        }

        // 合约期
        for(Entry<String, JSONArray> item : monthMap.entrySet()){
            if(hyKey.equals(item.getKey().toUpperCase().substring(0, 1))){
                actObj.getJSONObject(hyKey).getJSONObject("month").put(item.getKey(), item.getValue());
            } else{
                actObj.getJSONObject(ljKey).getJSONObject("month").put(item.getKey(), item.getValue());
            }
        }

        // 保底金额
        for(Entry<String, JSONArray> item : feeMap.entrySet()){
            if(hyKey.equals(item.getKey().toUpperCase().substring(0, 1))){
                actObj.getJSONObject(hyKey).getJSONObject("fee").put(item.getKey(), item.getValue());
            } else{
                actObj.getJSONObject(ljKey).getJSONObject("fee").put(item.getKey(), item.getValue());
            }
        }

        // 活动详情
        for(Entry<String, JSONArray> item : infoMap.entrySet()){
            if(hyKey.equals(item.getKey().toUpperCase().substring(0, 1))){
                actObj.getJSONObject(hyKey).getJSONObject("info").put(item.getKey(), item.getValue().get(0));
            } else{
                actObj.getJSONObject(ljKey).getJSONObject("info").put(item.getKey(), item.getValue().get(0));
            }
        }

        return actObj;
    }

    /**
     * @Title: validate
     * @Description:终端 校验 接口
     * @param phoneNo
     *            TODO
     * @param loginAccept:为查询接口返回的BATCH_NO
     * @param groudId:工号对应的渠道编码
     * @param loginNo:工号
     * @param imei:资源提供的串号
     * @param opType:合约机传4976，非合约机传4975
     * @return String:返回
     */
    public String validate(String loginAccept, String groudId, String loginNo, String resNo, String opType,
            String phoneNo, String token){
        try{
            checkParams(loginAccept, groudId, loginNo, resNo, opType, phoneNo);
            String result = sendCheckImeiRequest(loginAccept, groudId, loginNo, resNo, opType, phoneNo, token);
            logger.debug("result=" + result);
            return parseReuslt(result);
        }
        catch(IllegalArgumentException e){
            JSONObject joResponse = new JSONObject();
            joResponse.put(ClientApiConstant.Key.RESULT_CODE, ClientApiConstant.ResultCode.SERVER_EXCEPTION);
            joResponse.put(ClientApiConstant.Key.MESSAGE, e.getMessage());
            logger.error("IllegalArgumentException.result=" + joResponse.toString());
            return joResponse.toString();
        }
        catch(IOException e){
            /* 校验失败 */
            JSONObject joResponse = new JSONObject();
            joResponse.put(ClientApiConstant.Key.RESULT_CODE, ClientApiConstant.ResultCode.SERVER_EXCEPTION);
            joResponse.put(ClientApiConstant.Key.MESSAGE, e.getMessage() == null ? "网络问题" : e.getMessage());
            logger.error("IOException.result=" + joResponse.toString());
            return joResponse.toString();
        }
        catch(Exception e){
            // 其他类型的错误，如JSON,SQL
            JSONObject joResponse = new JSONObject();
            joResponse.put(ClientApiConstant.Key.RESULT_CODE, ClientApiConstant.ResultCode.SERVER_EXCEPTION);
            joResponse.put(ClientApiConstant.Key.MESSAGE, "Exception:" + e.getMessage());
            logger.error("Excpetion.result=" + joResponse.toString());
            return joResponse.toString();
        }
    }

    /**
     * @Title: parseReuslt
     * @Description:解析DPR返回结果
     * @param result:DPR返回JSON数据
     * @return String:解析结果
     */
    private String parseReuslt(String result){
        JSONObject jo = new JSONObject(result);
        JSONObject root = jo.getJSONObject("ROOT");

        int resCode = root.getInt("RETURN_CODE");
        int resultCode = ClientApiConstant.ResultCode.SUCCESS_CODE;
        String message = null;
        if(REST_RESULT_CODE_SUC == resCode){
            /* 校验成功 */
            resultCode = ClientApiConstant.ResultCode.SUCCESS_CODE;
            message = ClientApiConstant.Msg.SUCCESS;
        } else{
            /* 校验失败 */
            resultCode = ClientApiConstant.ResultCode.FAILED;
            message = "错误码" + resCode + ":" + root.getString("DETAIL_MSG");
        }
        JSONObject joResponse = new JSONObject();
        joResponse.put(ClientApiConstant.Key.RESULT_CODE, resultCode);
        joResponse.put(ClientApiConstant.Key.MESSAGE, message);
        logger.debug("parseReuslt,result=" + joResponse.toString());
        return joResponse.toString();
    }

    /**
     * @Title: checkParams
     * @Description:检查参数
     * @param phoneNo
     *            TODO
     * @param loginAccept:为查询接口返回的BATCH_NO
     * @param groudId:工号对应的渠道编码
     * @param loginNo:工号
     * @param imei:资源提供的串号
     * @param opType:合约机传4976，非合约机传4975
     * @throws IOException
     *             void
     */
    private void checkParams(String loginAccept, String groudId, String loginNo, String imei, String opType,
            String phoneNo) throws IllegalArgumentException{
        if(StrKit.isBlank(loginAccept)){
            throw new IllegalArgumentException("参数错误,batchno为空");
        }
        if(StrKit.isBlank(groudId)){
            throw new IllegalArgumentException("参数错误,groudid为空");
        }
        if(StrKit.isBlank(loginNo)){
            throw new IllegalArgumentException("参数错误,loginno为空");
        }
        if(StrKit.isBlank(imei)){
            throw new IllegalArgumentException("参数错误,imei为空");
        }
        if(StrKit.isBlank(opType)){
            throw new IllegalArgumentException("参数错误,optype为空");
        }
        if(StrKit.isBlank(phoneNo)){
            throw new IllegalArgumentException("参数错误,phoneNo为空");
        }
    }

    /**
     * @Title: sendCheckImeiRequest
     * @Description:发送校验请求并获取返回结果（DPR接口提供）
     * @param phoneNo
     *            TODO
     * @param loginAccept:为查询接口返回的BATCH_NO
     * @param groudId:工号对应的渠道编码
     * @param loginNo:工号
     * @param res_no:资源提供的串号
     * @param opType:合约机传4976，非合约机传4975
     * @return:DPR返回JSON数据
     * @throws IOException
     *             String
     */
    private String sendCheckImeiRequest(String loginAccept, String groudId, String loginNo, String resNo, String opType,
            String phoneNo, String token) throws IOException{
        String body = buildRequest(loginAccept, groudId, loginNo, resNo, opType, phoneNo);
        logger.debug("body = " + body);
        logger.debug("url = " + restHostPrefix + Constant.Url.CHECK_IMEI + "?token=" + token);
        String result = HttpUtil.syncPostJsonBody(restHostPrefix + Constant.Url.CHECK_IMEI + "?token=" + token,
                                                  MediaType.JSON_UTF_8, body, 30000);
        return result;
    }

    private String buildRequest(String loginAccept, String groudId, String loginNo, String resNo, String opType,
            String phoneNo){
        JSONObject root = new JSONObject();
        JSONObject body = new JSONObject();
        JSONObject requestInfo = new JSONObject();
        requestInfo.put("LOGIN_NO", loginNo);
        requestInfo.put("PHONE_NO", phoneNo);
        requestInfo.put("GROUP_ID", groudId);
        requestInfo.put("OP_CODE", opType);
        requestInfo.put("LOGIN_ACCEPT", loginAccept);
        requestInfo.put("OP_NOTE", "");
        requestInfo.put("RES_TYPE", "T");
        requestInfo.put("RES_NO", resNo);
        requestInfo.put("RES_OPR", "0");
        requestInfo.put("OLD_IMEI", "");
        requestInfo.put("COLOR_ID", "");

        body.put("PHONE_NO", phoneNo);// 为了路由加的
        body.put("REQUEST_INFO", requestInfo);

        root.put("BODY", body);
        return root.toString();
    }

}
